Building an Admin Dashboard Layout With CSS (and a Touch of JavaScript)

您所在的位置:网站首页 css overflow 101 build beautiful web pages Building an Admin Dashboard Layout With CSS (and a Touch of JavaScript)

Building an Admin Dashboard Layout With CSS (and a Touch of JavaScript)

2023-12-07 00:48| 来源: 网络整理| 查看: 265

In this tutorial, we’ll create a responsive admin dashboard layout with CSS and a touch of JavaScript. To build it, we’ll borrow some ideas from the WordPress dashboard, such as its collapsible sidebar menu.

Throughout the tutorial, we’ll face plenty of challenges, but ones that will give us good practice for enhancing our front-end skills. There’s also a video version which you can watch if you prefer.

Admin Dashboard Demo

Let’s have a look at the final admin dashboard demo. Pay attention to the following things:

Hit the Collapse button at the foot of the sidebar to see the collapsible nav in action. Hit the toggle switch at the foot of the sidebar to reveal the light and dark admin themes. Check out the full-screen version to play with its responsiveness.

1. Begin With the Page Markup

To kick off the markup we’ll need an SVG, a header, and a section:

1 ... 2 ... 3 ... SVG Sprites

As you might imagine with any admin dashboard we’re going to need a bunch of icons. Thankfully, Envato Elements provides an ever-expanding collection of useful vector icons, so let’s take advantage of that library and download these Trade and Dashboard Icons.

Trade and Dashboard IconsTrade and Dashboard IconsTrade and Dashboard Icons Trade and Dashboard Icons on Envato Elements

Rather than including them directly on the page via an img or svg tag, let’s go one step further and create an SVG sprite. To do this, we’ll wrap all the icons in an SVG container. The container should be hidden, so we’ll apply display: none to it. If we don’t hide it, a big empty area will appear at the top of the page.

Each icon will be placed inside a symbol element with a unique ID and a viewBox attribute which will depend on the icon size. We can then render the target icon whenever we need it by calling the use element (I’ll show you how in a minute). 

Additionally, we’ll put our logo within this container. 

Later, we’ll examine how the colors of these SVGs will change depending on the theme mode, but for now let’s just become familiar with the markup needed for the SVG sprite:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

And really, that’s all we need to create our inline SVG sprite.

Header

Moving on with our admin dashboard layout, let’s look at the page header. 

Within it, we’ll define a nav element that will serve as the wrapper for the following elements:

The logo. The Collapse button that will toggle the menu on mobile screens. The menu itself. This will contain the menu links, two headings, a light/dark mode switch, and the collapse/expand button. It might be more semantically correct to have two individual menus and place the headings outside them, but you can approach things differently if you prefer.

Here’s how it’ll look like on wide screens (>767px):

The header layout

The header structure:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Admin 16 17 18 19 20 21 22 Pages 23 24 25 26 27 28 29 30 31 32 33 Dark 34 35 36 37 38 39 40 Collapse 41 42 43 44 45

Notice two things in the code above:

How we use the use element to reference the target elements. The ARIA attributes (aria-expanded, aria-label, aria-hidden) that we add to the toggle buttons. These attributes will help us make the component a bit more accessible. Later, we’ll discuss how their values will be updated based on the button’s state. Section

The section will contain two nested sections.

1 2 3 Section #1

Inside the first section, we’ll place the search form and some info (name, avatar, and notifications) about the current logged-in user.

Here’s its appearance on wide screens (>767px):

The layout of the first sectionThe layout of the first sectionThe layout of the first section

The section structure:

1 2 3 4 5 6 7 8 9 10 11 ... 12 13 ... 14 15 16 17 18 19

Again, notice that we add some ARIA attributes to the submit button.

Section #2

Inside the second section, just for enriching the demo with some dummy content, we’ll place a bunch of article placeholders. These might typically contain tabular data, charts, or feeds of some kind.

“Use a maximum of 5–7 different widgets to create a view. Otherwise, it will be hard for a user to focus and get a clear overview.” – Taras Bakusevych

Here’s its appearance on wide screens (>767px):

The layout of the second sectionThe layout of the second sectionThe layout of the second section In accordance with UX best practices, you may not need this many sections

The section structure:

1 2 3 4 5 6 7 8 9 10 2. Define Some Basic Styles

With the markup for our admin dashboard ready, we’ll forge on with the CSS. The first step, as always, is to specify some CSS variables and common reset styles:

1 :root { 2 --page-header-bgColor: #242e42; 3 --page-header-bgColor-hover: #1d2636; 4 --page-header-txtColor: #dde9f8; 5 --page-header-headingColor: #7889a4; 6 --page-header-width: 220px; 7 --page-content-bgColor: #f0f1f6; 8 --page-content-txtColor: #171616; 9 --page-content-blockColor: #fff; 10 --white: #fff; 11 --black: #333; 12 --blue: #00b9eb; 13 --red: #ec1848; 14 --border-radius: 4px; 15 --box-shadow: 0 0 10px -2px rgba(0, 0, 0, 0.075); 16 --switch-bgLightModeColor: #87cefa; 17 --switch-sunColor: gold; 18 --switch-moonColor: #f4f4f4; 19 --switch-bgDarkModeColor: #1f1f27; 20 } 21 22 * { 23 padding: 0; 24 margin: 0; 25 box-sizing: border-box; 26 } 27 28 ul { 29 list-style: none; 30 } 31 32 a, 33 button { 34 color: inherit; 35 } 36 37 a { 38 text-decoration: none; 39 } 40 41 button { 42 background: none; 43 cursor: pointer; 44 } 45 46 input { 47 -webkit-appearance: none; 48 } 49 50 [type="checkbox"] { 51 position: absolute; 52 left: -9999px; 53 } 54 55 label { 56 cursor: pointer; 57 } 58 59 button, 60 input { 61 border: none; 62 } 63 64 svg { 65 display: block; 66 } 67 68 body { 69 font: 16px/1.5 "Lato", sans-serif; 70 } tip For simplicity, I won’t walk through all the CSS rules in the tutorial. There are almost 550 lines of CSS here. If you want to, you can check them all by clicking the CSS tab of the demo project. Besides that, if you are building a production site, it might be more manageable to use a CSS preprocessor like Sass for organizing these styles. 3. Define the Main Dashboard Styles

At this point, we’re ready to concentrate on the page styles.

Style the Header

The header will be a fixed position element. Its width will be 220px, and its height equal to the viewport height. In case its contents exceed the viewport height, a vertical scrollbar will appear.

The nav element will behave as a flex container with a minimum height of 100%. Remember that its direct children are three: 

The logo The mobile menu toggle button The menu

The toggle button will be visible only on small screens ( * { 16 width: 100%; 17 padding: 12px 15px; 18 } 19 20 .page-header .admin-menu .menu-heading h3 { 21 text-transform: uppercase; 22 letter-spacing: 0.15em; 23 font-size: 12px; 24 margin-top: 12px; 25 color: var(--page-header-headingColor); 26 } 27 28 .page-header .admin-menu a, 29 .page-header .admin-menu button { 30 display: flex; 31 align-items: center; 32 font-size: 0.9rem; 33 } Toggling Dark and Light Themes

To build the switch, we’ll borrow quite a lot of styles from another tutorial which explains how to create a toggle switch. Be sure to have a look and learn how we implement it with the CSS checkbox hack technique.

Our dashboard will support two theme options: the light option and the dark one. By default, the dark will be active and look like this:

The dark mode enabled

When we click on the switch its appearance will change as follows:

The light mode enabled

Here are the associated styles:

1 /*CUSTOM VARIABLES HERE*/ 2 3 .switch label { 4 display: grid; 5 grid-template-columns: auto auto; 6 grid-column-gap: 10px; 7 align-items: center; 8 justify-content: flex-start; 9 } 10 11 .switch span:first-child { 12 position: relative; 13 width: 50px; 14 height: 26px; 15 border-radius: 15px; 16 box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.4); 17 background: var(--switch-bgLightModeColor); 18 transition: all 0.3s; 19 } 20 21 .switch span:first-child::before, 22 .switch span:first-child::after { 23 content: ""; 24 position: absolute; 25 border-radius: 50%; 26 } 27 28 .switch span:first-child::before { 29 top: 1px; 30 left: 1px; 31 width: 24px; 32 height: 24px; 33 background: var(--white); 34 z-index: 1; 35 transition: transform 0.3s; 36 } 37 38 .switch span:first-child::after { 39 top: 50%; 40 right: 8px; 41 width: 10px; 42 height: 10px; 43 transform: translateY(-50%); 44 background: var(--switch-sunColor); 45 box-shadow: 0 0 4px 2px #ffdb1a; 46 } 47 48 .switch [type="checkbox"]:checked + label span:first-child { 49 background: var(--switch-bgDarkModeColor); 50 } 51 52 .switch [type="checkbox"]:focus + label span:first-child { 53 box-shadow: 0 3px 5px rgba(255, 255, 255, 0.25); 54 } 55 56 .switch [type="checkbox"]:checked + label span:first-child::before { 57 transform: translateX(24px); 58 } 59 60 .switch [type="checkbox"]:checked + label span:first-child::after { 61 left: 12px; 62 width: 15px; 63 height: 15px; 64 background: transparent; 65 box-shadow: -2px -5px 0 var(--switch-moonColor); 66 transform: translateY(-50%) rotate(-72deg); 67 } Page Content Styles

Remember that the .page-content section contains two sub-sections.

This section will be placed 220px away from the left side of the viewport. Plus, we’ll give it width: calc(100% - 220px). Note that its left property value is equal to the header width.

Its styles:

1 /*CUSTOM VARIABLES HERE*/ 2 3 .page-content { 4 position: relative; 5 left: var(--page-header-width); 6 width: calc(100% - var(--page-header-width)); 7 min-height: 100vh; 8 padding: 30px; 9 color: var(--page-content-txtColor); 10 background: var(--page-content-bgColor); 11 } Search and User Styles

Also, remember that the .search-and-user section contains two elements: the search form and the .admin-profile.

To lay it out, we’ll use CSS Grid. The search form will cover the full available space, and there will be a 50px gap between it and its sibling. Both siblings will be vertically aligned.

The submit button inside the form will be absolutely positioned. It will only contain a decorative icon, and we’ll therefore need an ARIA attribute to allow screenreaders to interpret it and thereby make it accessible.

The .admin-profile, which contains two elements, will behave as a flex container with vertically centered content. The badge (counter) element will be absolutely positioned inside its parent with horizontally and vertically centered content.

Here’s a part of the required styles for this section:

1 /*CUSTOM VARIABLES HERE*/ 2 3 .search-and-user { 4 display: grid; 5 grid-template-columns: 1fr auto; 6 grid-column-gap: 50px; 7 align-items: center; 8 background: var(--page-content-bgColor); 9 margin-bottom: 30px; 10 } 11 12 .search-and-user form { 13 position: relative; 14 } 15 16 .search-and-user form button { 17 position: absolute; 18 top: 50%; 19 right: 15px; 20 transform: translateY(-50%); 21 } 22 23 .search-and-user .admin-profile { 24 display: flex; 25 align-items: center; 26 } 27 28 .search-and-user .admin-profile .notifications { 29 position: relative; 30 } 31 32 .search-and-user .admin-profile .badge { 33 display: flex; 34 align-items: center; 35 justify-content: center; 36 position: absolute; 37 top: -10px; 38 right: -3px; 39 width: 18px; 40 height: 18px; 41 border-radius: 50%; 42 font-size: 10px; 43 color: var(--white); 44 background: var(--red); 45 } Grid Styles

To lay out the articles on our admin dashboard, we’ll take advantage of CSS Grid. We’ll give all articles a fixed height of 300px. Apart from the first and last articles which will cover the full parent width, all the others will be part of a two-column layout.

The associated styles:

1 /*CUSTOM VARIABLES HERE*/ 2 3 .page-content .grid { 4 display: grid; 5 grid-template-columns: repeat(2, 1fr); 6 grid-gap: 30px; 7 } 8 9 .page-content .grid > article { 10 display: flex; 11 height: 300px; 12 background: var(--page-content-blockColor); 13 border-radius: var(--border-radius); 14 box-shadow: var(--box-shadow); 15 } 16 17 .page-content .grid > article:first-child, 18 .page-content .grid > article:last-child { 19 grid-column: 1 / -1; 20 } 4. Toggle Header

Each time we click on the collapse/expand button, the header state will change. If it’s expanded, it will collapse (leaving just icon variants of the menu items), and vice versa. 

collapsing menu with icons

Keep in mind that this functionality will be available only on screens greater than 767px. For smaller screens, our header will have a different layout, which we’ll get to shortly.

During the collapsed state of the header, the body element receives the collapsed class. At that point, the following things happen:

The header shrinks. Its width changes from 220px to 40px. In response to this, the .page-content section grows. Specifically, its width changes from width: calc(100% - 220px) to width: calc(100% - 40px). In addition, its left property value becomes 40px instead of 220px. The logo, the menu headings, the menu links text, the light/dark theme switcher, and the menu button text disappear. The aria-expanded and aria-label attribute values of the toggle button are updated. Plus, its icon is rotated 180 degrees, so it looks like an expand icon.

Here’s the JavaScript code that implements this functionality:

1 const body = document.body; 2 const collapseBtn = document.querySelector(".admin-menu .collapse-btn"); 3 const collapsedClass = "collapsed"; 4 5 collapseBtn.addEventListener("click", function() { 6 body.classList.toggle(collapsedClass); 7 this.getAttribute("aria-expanded") == "true" 8 ? this.setAttribute("aria-expanded", "false") 9 : this.setAttribute("aria-expanded", "true"); 10 this.getAttribute("aria-label") == "collapse menu" 11 ? this.setAttribute("aria-label", "expand menu") 12 : this.setAttribute("aria-label", "collapse menu"); 13 });

And all the associated styles:

1 /*CUSTOM VARIABLES HERE*/ 2 3 @media screen and (min-width: 768px) { 4 .collapsed .page-header { 5 width: 40px; 6 } 7 8 .collapsed .page-header .admin-menu li > * { 9 padding: 10px; 10 } 11 12 .collapsed .page-header .logo, 13 .collapsed .page-header .admin-menu span, 14 .collapsed .page-header .admin-menu .menu-heading { 15 display: none; 16 } 17 18 .collapsed .page-header .admin-menu svg { 19 margin-right: 0; 20 } 21 22 .collapsed .page-header .collapse-btn svg { 23 transform: rotate(180deg); 24 } 25 26 .collapsed .page-content { 27 left: 40px; 28 width: calc(100% - 40px); 29 } 30 } 5. Toggle Theme Switch

Each time we click on the toggle switch, the dashboard colors will change.

light and dark toggle switchlight and dark toggle switchlight and dark toggle switch

Remember that initially the dark mode will be enabled. But, as soon as the light mode becomes active, the html element will receive the light-mode class.

The html light mode classThe html light mode classThe html light mode class

This class will update/override the values of many of the predefined CSS variables (especially the color ones) and hence change the theme appearance.

Here’s the required JavaScript code:

1 const html = document.documentElement; 2 const switchLabel = document.querySelector(".switch label"); 3 const switchLabelText = switchLabel.querySelector("span:last-child"); 4 const lightModeClass = "light-mode"; 5 6 switchInput.addEventListener("input", function () { 7 html.classList.toggle(lightModeClass); 8 if (html.classList.contains(lightModeClass)) { 9 switchLabelText.textContent = "Light"; 10 } else { 11 switchLabelText.textContent = "Dark"; 12 } 13 });

And the associated styles:

1 /*CUSTOM VARIABLES HERE*/ 2 3 .light-mode { 4 --page-header-bgColor: #f1efec; 5 --page-header-bgColor-hover: #b9e4e0; 6 --page-header-txtColor: #2c303a; 7 --page-header-headingColor: #979595; 8 --page-content-bgColor: #fff; 9 --box-shadow: 0 0 10px -2px rgba(0, 0, 0, 0.25); 10 } 11 12 .light-mode .page-header .admin-menu a:hover, 13 .light-mode .page-header .admin-menu a:focus, 14 .light-mode .page-header .admin-menu button:hover, 15 .light-mode .page-header .admin-menu button:focus { 16 color: var(--black); 17 } 18 19 .light-mode .page-header .logo svg, 20 .light-mode .page-header .admin-menu a:hover svg, 21 .light-mode .page-header .admin-menu a:focus svg, 22 .light-mode .page-header .admin-menu button:hover svg, 23 .light-mode .page-header .admin-menu button:focus svg { 24 fill: var(--black); 25 } 26 27 .light-mode .switch [type="checkbox"]:focus + label span:first-child { 28 box-shadow: 0 3px 5px rgba(0, 0, 0, 0.25); 29 } 30 31 @media screen and (max-width: 767px) { 32 .light-mode .search-and-user .admin-profile svg { 33 fill: var(--black); 34 } 35 } Persist Selected Mode on Page Load

But we haven’t finished yet! It would be really nice if we could store the user’s theme preference and enable it each time they revisit the admin. We can achieve this by taking advantage of local storage.

Store the preferred theme mode in local storageStore the preferred theme mode in local storageStore the preferred theme mode in local storage

Let’s look at the JavaScript code that will handle this logic:

1 ... 2 3 if (localStorage.getItem("dark-mode") === "false") { 4 html.classList.add(lightModeClass); 5 switchInput.checked = false; 6 switchLabelText.textContent = "Light"; 7 } 8 9 switchInput.addEventListener("input", function () { 10 if (html.classList.contains(lightModeClass)) { 11 localStorage.setItem("dark-mode", "false"); 12 } else { 13 localStorage.setItem("dark-mode", "true"); 14 } 15 });

From here, you can go deeper and make even more complex assumptions by using the prefers-color-scheme CSS media feature. For example, if the user hasn’t selected any mode, you can display the one that respects their operating system preference. But for now, let’s keep things simple.

6. Show Tooltip on Admin Menu Items

At this point, let’s add another new feature to the collapsible header.

As we discussed in the previous section, when the header becomes collapsed, the text of the menu links will disappear. This means, at that point, only the SVG icons will be visible. So, let’s display a tooltip that will give users a better understanding of what each link does.

To do so, each time a menu link (icon) is being hovered over, we’ll add the title attribute to it, with the value being its span’s text. But again, that should happen only when the header is collapsed and the window width is at least 768px.

collapsed menu icon tooltips

Here’s the corresponding JavaScript: 

1 const body = document.body; 2 const menuLinks = document.querySelectorAll(".admin-menu a"); 3 const collapsedClass = "collapsed"; 4 5 for (const link of menuLinks) { 6 link.addEventListener("mouseenter", function () { 7 if ( 8 body.classList.contains(collapsedClass) && 9 window.matchMedia("(min-width: 768px)").matches 10 ) { 11 const tooltip = this.querySelector("span").textContent; 12 this.setAttribute("title", tooltip); 13 } else { 14 this.removeAttribute("title"); 15 } 16 }); 17 } 7. Going Responsive

On screens up to 767px wide, our page will look like this:

The mobile layoutThe mobile layoutThe mobile layout

That’s a big difference from our sidebar arrangement, right? Let’s highlight the most important differences compared to the desktop version:

Both the header and .page-content have position: static and width: 100%. The flex direction of the nav element changes from column to row. The mobile menu toggle button becomes visible. The menu is absolutely positioned right underneath the header and initially hidden. It will become visible each time we click on the toggle button.  The collapse/expand button and the .greeting element are hidden. The .search-and-user section is absolutely positioned and placed right next to the mobile menu toggle button. 

Below you can see a part of the responsive styles:

1 @media screen and (max-width: 767px) { 2 .page-header, 3 .page-content { 4 position: static; 5 width: 100%; 6 } 7 8 .page-header nav { 9 flex-direction: row; 10 } 11 12 .page-header .toggle-mob-menu { 13 display: block; 14 } 15 16 .page-header .admin-menu { 17 position: absolute; 18 left: 98px; 19 top: 57px; 20 margin-top: 0; 21 z-index: 2; 22 border-radius: var(--border-radius); 23 background: var(--page-header-bgColor); 24 visibility: hidden; 25 opacity: 0; 26 transform: scale(0.95); 27 transition: all 0.2s; 28 } 29 30 .page-header .admin-menu li:last-child button, 31 .search-and-user .admin-profile .greeting { 32 display: none; 33 } 34 35 .search-and-user { 36 position: absolute; 37 left: 131px; 38 top: 10px; 39 padding: 0; 40 grid-column-gap: 5px; 41 width: calc(100% - 141px); 42 border-radius: var(--border-radius); 43 background: transparent; 44 } 45 } 8. Toggle Mobile Menu

Each time we click on the toggle button, the menu state will change. If it’s expanded, it will collapse, and vice versa.

mobile menu toggle

During the expanded state of the menu, the body element receives the mob-menu-opened class. At that point, the following things happen:

The menu appears. The aria-expanded and aria-label attribute values of the toggle button are updated. Plus, its icon is rotated 180 degrees, so it looks like an expand icon.

Here’s the required JavaScript code:

1 const body = document.body; 2 const toggleMobileMenu = document.querySelector(".toggle-mob-menu"); 3 4 toggleMobileMenu.addEventListener("click", function() { 5 body.classList.toggle("mob-menu-opened"); 6 this.getAttribute("aria-expanded") == "true" 7 ? this.setAttribute("aria-expanded", "false") 8 : this.setAttribute("aria-expanded", "true"); 9 this.getAttribute("aria-label") == "open menu" 10 ? this.setAttribute("aria-label", "close menu") 11 : this.setAttribute("aria-label", "open menu"); 12 });

And the associated CSS:

1 .page-header .toggle-mob-menu svg { 2 transition: transform 0.2s; 3 } 4 5 .page-header .admin-menu { 6 transition: all 0.2s; 7 } 8 9 .mob-menu-opened .toggle-mob-menu svg { 10 transform: rotate(180deg); 11 } 12 13 .mob-menu-opened .page-header .admin-menu { 14 transform: scale(1); 15 visibility: visible; 16 opacity: 1; 17 } Conclusion

That’s it, folks! We successfully built a fully functional admin dashboard layout. You’ll be able to expand on this foundation to create all kinds of admin interfaces. Hopefully, you enjoyed this journey as much as I did!

A Note on Accessibility

Just a last note: I’m certainly not an accessibility expert, yet I tried to make this UI more accessible by adding some common ARIA attributes. During this process, I checked the WordPress and CodePen dashboards for reference. There might be additional ARIA attributes that could have been included in the code. For example, I excluded the aria-controls attribute which is responsible for identifying the related content, but that was because Aria-Controls is Poop.

As a next step, make sure to optimize the code by using a CSS preprocessor and group the JavaScript code into functions. And if you plan to use this admin in a real project, I’d love to know it!

As always, thanks for reading!

FREE 1.1 Hours Build a CSS and JavaScript Dashboard UI

Learn how to build a simple responsive admin dashboard UI, which features a collapsible sidebar, icons, and a dark mode toggle switch.

Build a Better Responsive Admin Dashboard UI | HTML, CSS, JavaScript More Admin Dashboard UI Resources 20 Feature-Packed Bootstrap Admin Templates Ian Yates 10 Jun 2021 How to Build a SaaS Dashboard in React With Google Sheets and FusionCharts Gagan Sikri 18 Dec 2018 20+ Best Dashboard UI Kits for Figma 2023 Brenda Barron 30 Jun 2022 12+ Dashboard UI Concepts to Inspire Your Designs Brenda Barron 01 Jun 2023


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3